package com.vinjune.algorithm.concurrentDemo;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by 835888 on 2015/11/16.
 */
public class TreadCountDemo {

    private static int count = 0;

//    1.非线程安全问题，共享变量乱套了
    public static class CountThread implements Runnable {

//        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
                System.out.println(Thread.currentThread().getName() + ", count = " + count);
            }
        }

    }

    private static final Object lock = new Object();// 这边使用的lock对象

    public static class CountThread2 implements Runnable {// 这边使用的是互斥锁方式

//        @Override
        public void run() {
            synchronized (lock) {// 使用互斥锁方式处理
                for (int i = 0; i < 100; i++) {
                    count++;
                    System.out.println(Thread.currentThread().getName() + ", count = " + count);
                }
            }
        }

    }

    private static AtomicInteger ai = new AtomicInteger();// 这边使用的是并发包的AtomicXXX类，使用的是CAS方式：compare and swap

    public static class CountThread3 implements Runnable {// AtomicInteger内部的CAS实现方式，采用的是：循环、判断、设置三部曲方式

//        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                int tmp = ai.incrementAndGet();// 采用CAS方式处理
                System.out.println(Thread.currentThread().getName() + ", count = " + tmp);
            }
        }

    }


    private static volatile int countV = 0;// 定义成volatile，让多线程感知，因为值是放在主存中

    public static class CountThread4 implements Runnable {// volatile定义的变量只是说放到了主存，当时++操作并不是原子操作，这个要小心

//        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(50);// 这边让线程休眠下，增加出错概率
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countV++;// volatile要正确使用，不是说定义成volatile就是安全的，还是要注意++ --操作并不是原子操作
                System.out.println(Thread.currentThread().getName() + ", count = " + countV);
            }
        }

    }

    public static <T> void testTemplate(T t) throws InstantiationException, IllegalAccessException, InterruptedException {
        for (int i = 0; i < 5; i++) {
            if (t instanceof Runnable) {
                Class<?> c = t.getClass();
                Object object = c.newInstance();
                new Thread((Runnable) object).start();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException, InstantiationException, IllegalAccessException {
        // 1.测试1
//         testTemplate(new CountThread());
        // 2.测试2
//         testTemplate(new CountThread2());
        // 3.测试3
//         testTemplate(new CountThread3());
        // 4.测试4
        testTemplate(new CountThread4());
        Thread.sleep(15000);
        System.out.println(count);
        System.out.println(ai.get());
        System.out.println(countV);
    }
}
